<script setup lang="ts">
import { computed, onBeforeMount, ref, watch } from 'vue';
import AuColorPickerRing from './AuColorPickerRing.vue'
import { HEX, HSV, RGB } from 'color-convert/conversions';
import cc from 'color-convert'
import { isValidHex } from './utils/isValidHex';
import { PickerProps } from './common/pickerProps'
import { useEntryStyles } from './common/useEntryStyles'
import { clickPackageName } from './utils/clickPackageName';
import { myProperHex } from './utils/myProperHex';
import { usePanelStyles } from './common/usePanelStyles';

const props = defineProps<PickerProps>()
const ring = ref<InstanceType<typeof AuColorPickerRing>>()

const { hexValue, panelShow, closePanel, togglePanel, entryStylesActual } = useEntryStyles(props)
const { panelStyles } = usePanelStyles(props)

function ringChanged(hex:HEX){
    hexValue.value = myProperHex(hex)
    emitChange()
}

const mode = ref<'rgb'|'hsv'|'hex'>('hex')
const rgb = computed<RGB>(()=>{
    return cc.hex.rgb(hexValue.value)
})
const hsv = computed<HSV>(()=>{
    return cc.hex.hsv(hexValue.value)
})

function hexBlur(e:Event){
    const target = e.target as HTMLInputElement
    if('value' in target){
        const hexInputed = target.value
        if(hexInputed){
            if(isValidHex(hexInputed)){
                hexValue.value = myProperHex(hexInputed)
                ring.value?.enforceTo(hexValue.value)
                emitChange()
                return
            }
        }
        target.value = hexValue.value
    }
}
function rgbBlur(e:Event, channel:'r'|'g'|'b'){
    const target = e.target as HTMLInputElement
    if('value' in target){
        const channelInputed = target.value
        if(channelInputed){
            let value = parseInt(channelInputed)
            if(!isNaN(value)){
                //rgb值clamp到0-255区间
                if(value>255)
                    value = 255
                else if(value<0)
                    value = 0
                const newRgb:RGB = [...rgb.value]
                if(channel=='r')
                    newRgb[0] = value
                else if(channel=='g')
                    newRgb[1] = value
                else
                    newRgb[2] = value
                hexValue.value = myProperHex(cc.rgb.hex(newRgb))
                ring.value?.enforceTo(hexValue.value)
                target.value = value.toString()
                emitChange()
                return
            }else{
                target.value = '0'
            }
        }
    }
}
function hsvBlur(e:Event, channel:'h'|'s'|'v'){
    const target = e.target as HTMLInputElement
    if('value' in target){
        const channelInputed = target.value
        if(channelInputed){
            let value = parseInt(channelInputed)
            if(!isNaN(value)){
                if(channel==='h'){
                    //hue值clamp到0-359区间
                    if(value>359)
                        value = 359
                }else{
                    //sat和val值clamp到0-100区间
                    if(value>100)
                        value = 100
                }
                if(value<0)
                    value = 0
                const newHsv:HSV = [...hsv.value]
                if(channel=='h')
                    newHsv[0] = value
                else if(channel=='s')
                    newHsv[1] = value
                else
                    newHsv[2] = value
                hexValue.value = myProperHex(cc.hsv.hex(newHsv))
                target.value = value.toString()
                ring.value?.enforceTo(hexValue.value)
                emitChange()
                return
            }else{
                target.value = '0'
            }
        }
    }
}

function emitChange(){
    emit('change', hexValue.value)
}
function getCurrentHex(){
    return hexValue.value
}
function enforceTo(newHexValue:string){
    if(isValidHex(newHexValue)){
        const hex = myProperHex(newHexValue)
        hexValue.value = hex
        ring.value?.enforceTo(hex)
    }
}

onBeforeMount(()=>{
    if(props.initial){
        enforceTo(props.initial)
    }
})
const emit = defineEmits<{
    (e:'change', hexStr:string):void
    (e:'done', hexStr:string):void
}>()
defineExpose({closePanel, getCurrentHex, enforceTo})
watch(panelShow, newval=>{
    if(newval===false){
        emit('done', hexValue.value)
    }
})
</script>

<template>
<div class="acp">
    <div :class="entryClassName || 'acpEntry'" :style="entryStylesActual" @click="togglePanel"></div>
    <div class="acpPanel" v-if="panelShow" :style="panelStyles" @click="e=>panelClickStopPropagation && e.stopPropagation()">
        <div class="acpRing">
            <AuColorPickerRing ref="ring" :initial-hex="hexValue" @changed="ringChanged" :show-package-name="showPackageName"></AuColorPickerRing>
        </div>
        <div class="acpParams">
            <select v-model="mode">
                <option :value="'hex'">HEX</option>
                <option :value="'rgb'">RGB</option>
                <option :value="'hsv'">HSV</option>
            </select>
            <div v-if="mode=='hex'" class="acpSingleInput">
                <input :value="hexValue" @blur="hexBlur" spellcheck="false" maxlength="7"/>
            </div>
            <div v-else-if="mode=='rgb'" class="acpTripleInputs">
                <input :value="rgb[0]" @blur="e=>rgbBlur(e, 'r')"/>
                <input :value="rgb[1]" @blur="e=>rgbBlur(e, 'g')"/>
                <input :value="rgb[2]" @blur="e=>rgbBlur(e, 'b')"/>
            </div>
            <div v-else class="acpTripleInputs">
                <input :value="hsv[0]" @blur="e=>hsvBlur(e, 'h')"/>
                <input :value="hsv[1]" @blur="e=>hsvBlur(e, 's')"/>
                <input :value="hsv[2]" @blur="e=>hsvBlur(e, 'v')"/>
            </div>
        </div>
        <div class="acpDoneBtn">
            <button @click="closePanel">OK</button>
        </div>
        <div v-if="showPackageName" class="acpPackageName" @click="clickPackageName">
            au-color-picker
        </div>
    </div>
</div>
</template>

<style scoped lang="scss">
@use '../style.scss';

.acpPackageName{
    position: absolute;
    left: 2px;
    bottom: 3px;
    font-size: 8px;
    color: #ccc;
    text-align: right;
    cursor: pointer;
    user-select: none;
}

.acpParams {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 5px;

    select,
    input {
        margin: 0px;
        padding: 2px;
        display: block;
        font-size: 16px;
        box-sizing: border-box;
        height: 24px;
        line-height: 24px;
    }

    select{
        user-select: none;
    }
    input {
        text-align: center;
    }

    .acpSingleInput {
        input {
            width: 120px;
        }
    }

    .acpTripleInputs {
        display: flex;
        justify-content: space-around;

        input {
            width: 40px;
        }
    }
}
</style>
